//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
//
/// \file optical/wls/src/WLSDetectorConstruction.cc
/// \brief Implementation of the WLSDetectorConstruction class
//
//

#include "WLSDetectorConstruction.hh"

#include "WLSDetectorMessenger.hh"
#include "WLSMaterials.hh"
#include "WLSPhotonDetSD.hh"

#include "globals.hh"
#include "G4Box.hh"
#include "G4EllipticalTube.hh"
#include "G4ios.hh"
#include "G4GeometryManager.hh"
#include "G4LogicalBorderSurface.hh"
#include "G4LogicalSkinSurface.hh"
#include "G4LogicalVolume.hh"
#include "G4LogicalVolumeStore.hh"
#include "G4Material.hh"
#include "G4NistManager.hh"
#include "G4OpticalSurface.hh"
#include "G4PhysicalConstants.hh"
#include "G4PhysicalVolumeStore.hh"
#include "G4PVPlacement.hh"
#include "G4RunManager.hh"
#include "G4SDManager.hh"
#include "G4SolidStore.hh"
#include "G4SystemOfUnits.hh"
#include "G4Tubs.hh"
#include "G4UserLimits.hh"

#include "G4VisAttributes.hh"
#include "G4Colour.hh"

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

WLSDetectorConstruction::WLSDetectorConstruction()
    : fVisAttributes()
{
  fDetectorMessenger = new WLSDetectorMessenger(this);

  fMPPCHalfL = fWLSfiberRY;
  fClrfiberZ = fMPPCZ + 0.1 * mm;
  fHoleLength = fBarLength;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

WLSDetectorConstruction::~WLSDetectorConstruction()
{
  delete fDetectorMessenger;
  delete fMaterials;
  for (auto visAttributes : fVisAttributes)
  {
    delete visAttributes;
  }
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4VPhysicalVolume *WLSDetectorConstruction::Construct()
{
  if (fPhysiWorld)
  {
    G4GeometryManager::GetInstance()->OpenGeometry();
    G4PhysicalVolumeStore::GetInstance()->Clean();
    G4LogicalVolumeStore::GetInstance()->Clean();
    G4SolidStore::GetInstance()->Clean();
    G4LogicalSkinSurface::CleanSurfaceTable();
    G4LogicalBorderSurface::CleanSurfaceTable();
  }

  fMaterials = WLSMaterials::GetInstance();
  UpdateGeometryParameters();

  return ConstructDetector();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4VPhysicalVolume *WLSDetectorConstruction::ConstructDetector()
{
  auto Polystyrene = FindMaterial("Polystyrene");
  auto fpethylene = FindMaterial("FPethylene");
  auto pethylene = FindMaterial("Pethylene");
  auto silicone = FindMaterial("Silicone");
  auto pmma = FindMaterial("PMMA");
  auto aluminum = FindMaterial("G4_Al");
  auto air = FindMaterial("G4_AIR");
  G4NistManager *nist = G4NistManager::Instance();
  G4Material *pb = nist->FindOrBuildMaterial("G4_Pb");
  G4Material *fe = nist->FindOrBuildMaterial("G4_Fe");
  G4Material *al = nist->FindOrBuildMaterial("G4_Al");
  // G4cout << "\nMaterial Properties Table for G4_AIR:" << G4endl;
  // air->GetMaterialPropertiesTable()->DumpTable();

  //--------------------------------------------------
  // World 世界
  //--------------------------------------------------

  G4VSolid *solidWorld =
      new G4Box("World", 10.0 * m, 10.0 * m, 10.0 * m);
  fLogicWorld =
      new G4LogicalVolume(solidWorld, air, "World");

  fPhysiWorld =
      new G4PVPlacement(nullptr, G4ThreeVector(), fLogicWorld, "World", nullptr,
                        false, 0);
  //--------------------------------------------------
  // 透射物
  //--------------------------------------------------
  G4LogicalVolume *logicShape1 = nullptr;
  G4VPhysicalVolume *physiShape1 = nullptr;
  G4VSolid *solidShape1 = new G4Box("Shape1", fShape1HalfLength, 5. * cm, 5. * cm);

  logicShape1 =
      new G4LogicalVolume(solidShape1, pb, "Shape1");

  //--------------------------------------------------
  // Fiber Construction 光纤
  //--------------------------------------------------

  // Boundary Surface Properties
  G4OpticalSurface *opSurface = nullptr;

  if (fSurfaceRoughness < 1.)
    opSurface = new G4OpticalSurface("RoughSurface", glisur, ground,
                                     dielectric_dielectric, fSurfaceRoughness);

  G4LogicalVolume *logicWLSfiber = nullptr;
  G4LogicalVolume *logicClad1 = nullptr;
  G4LogicalVolume *logicClad2 = nullptr;
  G4VPhysicalVolume *physiClad1 = nullptr;
  G4VPhysicalVolume *physiClad2 = nullptr;

  // Determine the number of cladding layers to be built

  //--------------------------------------------------
  // Cladding 1
  //--------------------------------------------------

  G4cout << "\nMaterial Properties Table for pmma:" << G4endl;
  pmma->GetMaterialPropertiesTable()->DumpTable();

  G4VSolid *solidClad1;

  if (fXYRatio == 1.) // 圆柱
    solidClad1 = new G4Tubs("Clad1", 0., fClad1RY, fClad1Z, 0., twopi);
  else // 椭圆柱
    solidClad1 = new G4EllipticalTube("Clad1", fClad1RX, fClad1RY, fClad1Z);

  logicClad1 =
      new G4LogicalVolume(solidClad1, pmma, "Clad1");

  //--------------------------------------------------
  // WLS Fiber 光纤
  //--------------------------------------------------

  G4cout << "\nMaterial Properties Table for Polystyrene:" << G4endl;
  Polystyrene->GetMaterialPropertiesTable()->DumpTable();

  G4VSolid *solidWLSfiber;
  G4VPhysicalVolume *physiWLSfiber;

  if (fXYRatio == 1.) // 圆柱
  {
    solidWLSfiber = new G4Tubs("WLSFiber", 0., fWLSfiberRY, fWLSfiberZ, 0., twopi);
  }
  else // 椭圆柱
  {
    solidWLSfiber = new G4EllipticalTube("WLSFiber", fWLSfiberRX, fWLSfiberRY, fWLSfiberZ);
  }

  logicWLSfiber = new G4LogicalVolume(solidWLSfiber, Polystyrene, "WLSFiber");

  logicWLSfiber->SetUserLimits(new G4UserLimits(DBL_MAX, DBL_MAX, 10. * ms));

  //--------------------------------------------------
  // Clear Fiber (Coupling Layer)Couple
  //--------------------------------------------------
  //

  G4VSolid *solidCouple =
      new G4Tubs("ClearFiber", 0., fClad1RY, fClrfiberZ, 0., twopi);
  auto logicCouple = new G4LogicalVolume(solidCouple, silicone, "ClearFiber");

  //--------------------------------------------------
  // PhotonDet 灵敏探测器
  //--------------------------------------------------

  // Physical Construction
  G4VSolid *solidPhotonDet = nullptr;
  G4VPhysicalVolume *physiPhotoDet = nullptr;
  if (fMPPCShape == "Square") // 立方体
  {
    solidPhotonDet = new G4Box("PhotonDet", fClad1RY, fClad1RY, fMPPCZ);
  }
  else // 圆柱
  {
    solidPhotonDet = new G4Tubs("PhotonDet", 0., fClad1RY, fMPPCZ, 0., twopi);
  }

  auto logicPhotonDet = new G4LogicalVolume(solidPhotonDet, aluminum, "PhotonDet_LV");

  // PhotonDet Surface Properties
  auto photonDetSurface = new G4OpticalSurface(
      "PhotonDetSurface", glisur, ground, dielectric_metal, fMPPCPolish);

  auto photonDetSurfaceProperty = new G4MaterialPropertiesTable();

  std::vector<G4double> p_mppc = {2.00 * eV, 3.47 * eV};
  std::vector<G4double> refl_mppc = {fMPPCReflectivity, fMPPCReflectivity};
  std::vector<G4double> effi_mppc = {1., 1.};

  photonDetSurfaceProperty->AddProperty("REFLECTIVITY", p_mppc, refl_mppc); // 反射率
  photonDetSurfaceProperty->AddProperty("EFFICIENCY", p_mppc, effi_mppc);   // 效率

  photonDetSurface->SetMaterialPropertiesTable(photonDetSurfaceProperty);

  new G4LogicalSkinSurface("PhotonDetSurface", logicPhotonDet, photonDetSurface);

  // 统一放置
  if (fNumOfFibers == 1) // 1根光纤
  {
    physiClad1 = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.),
                                   logicClad1, "Clad1", fLogicWorld, false, 0);

    new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fCoupleOrigin), logicCouple,
                      "ClearFiber", fLogicWorld, false, 0);

    new G4PVPlacement(nullptr, G4ThreeVector(0., 0., -1 * fCoupleOrigin), logicCouple,
                      "ClearFiber", fLogicWorld, false, 1);
  }
  else
  {
    for (int i = 0; i < fNumOfFibers; i++)
    {
      G4double y1 = (i - fNumOfFibers / 2) * fClad1RY * 2 + i * 0.01 * mm;
      physiClad1 = new G4PVPlacement(nullptr, G4ThreeVector(-1 * fFiberSpaceHalfL, y1, 0.),
                                     logicClad1, "Clad1", fLogicWorld, false, i, 0);

      G4double y2 = (i - fNumOfFibers / 2) * fClad1RY * 2 + i * 0.01 * mm;

      new G4PVPlacement(nullptr, G4ThreeVector(-1 * fFiberSpaceHalfL, y2, fCoupleOrigin), logicCouple,
                        "ClearFiber", fLogicWorld, false, i, 0);

      new G4PVPlacement(nullptr, G4ThreeVector(-1 * fFiberSpaceHalfL, y2, -1. * fMPPCOriginZ), logicCouple,
                        "ClearFiber", fLogicWorld, false, (i + fNumOfFibers), 0);

      if (fNumOfFiberLayers == 2) // 第2层光纤
      {
        physiClad1 = new G4PVPlacement(nullptr, G4ThreeVector(fFiberSpaceHalfL, y1, 0.),
                                       logicClad1, "Clad1", fLogicWorld, false, i + fNumOfFibers, 0);

        new G4PVPlacement(nullptr, G4ThreeVector(fFiberSpaceHalfL, y2, fCoupleOrigin), logicCouple,
                          "ClearFiber", fLogicWorld, false, i + 2 * fNumOfFibers, 0);

        new G4PVPlacement(nullptr, G4ThreeVector(fFiberSpaceHalfL, y2, -1. * fMPPCOriginZ), logicCouple,
                          "ClearFiber", fLogicWorld, false, (i + 3 * fNumOfFibers), 0);
      }
    }
  }
  physiWLSfiber = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.),
                                    logicWLSfiber, "WLSFiber", logicClad1, false, 0);

  physiPhotoDet = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.), logicPhotonDet,
                                    "PhotonDet", logicCouple, false, 0);

  if (fShape1Toggle)
  {
    physiShape1 = new G4PVPlacement(nullptr, G4ThreeVector(0, 0, 0),
                                    logicShape1, "Shape1", fLogicWorld, false, 0);
  }
  // Place the rough surface only if needed
  if (opSurface)
  {
    new G4LogicalBorderSurface("surfaceClad1Out", physiClad1, fPhysiWorld, opSurface);

    new G4LogicalBorderSurface("surfaceClad1In", fPhysiWorld, physiClad1, opSurface);

    new G4LogicalBorderSurface("surfaceWLSOut", physiWLSfiber, physiClad1, opSurface);

    new G4LogicalBorderSurface("surfaceWLSIn", physiClad1, physiWLSfiber, opSurface);
  }
  // visualization attributes -------------------------------------------------

  auto visAttributes = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
  visAttributes->SetVisibility(false);
  fLogicWorld->SetVisAttributes(visAttributes);
  fVisAttributes.push_back(visAttributes);

  if (logicShape1 != nullptr)
  {
    auto visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 1.0, 0.5));
    visAttributes->SetVisibility(true);
    logicShape1->SetVisAttributes(visAttributes);
    fVisAttributes.push_back(visAttributes);
  }
  if (logicClad1 != nullptr)
  {
    visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.5, 0.5));
    visAttributes->SetVisibility(true);
    logicClad1->SetVisAttributes(visAttributes);
    fVisAttributes.push_back(visAttributes);
  }

  visAttributes = new G4VisAttributes(G4Colour(0.8, 0.8, 1.0));
  visAttributes->SetVisibility(true);
  logicWLSfiber->SetVisAttributes(visAttributes);
  fVisAttributes.push_back(visAttributes);

  visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 0.5, 0.5));
  visAttributes->SetVisibility(true);
  logicCouple->SetVisAttributes(visAttributes);
  fVisAttributes.push_back(visAttributes);

  visAttributes = new G4VisAttributes(G4Colour(1.0, 0.0, 0.0, 0.5));
  visAttributes->SetVisibility(true);
  logicPhotonDet->SetVisAttributes(visAttributes);
  fVisAttributes.push_back(visAttributes);

  return fPhysiWorld;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::ConstructSDandField()
{
  if (!fmppcSD.Get())
  {
    G4String mppcSDName = "WLS/PhotonDet";
    auto mppcSD = new WLSPhotonDetSD(mppcSDName);
    G4SDManager::GetSDMpointer()->AddNewDetector(mppcSD);
    fmppcSD.Put(mppcSD);
  }
  SetSensitiveDetector("PhotonDet_LV", fmppcSD.Get(), true);
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::UpdateGeometryParameters()
{
  fWLSfiberRX = fXYRatio * fWLSfiberRY;

  // fClad1RX = fWLSfiberRX + 0.03 * fWLSfiberRX;
  // fClad1RY = fWLSfiberRY + 0.03 * fWLSfiberRY;
  fClad1RX = fWLSfiberRX + fClad1RY - fWLSfiberRY;
  fClad1Z = fWLSfiberZ;

  // fClad2RX = fClad1RX + 0.03 * fWLSfiberRX;
  // fClad2RY = fClad1RY + 0.03 * fWLSfiberRY;
  // fClad2Z = fWLSfiberZ;

  // fWorldSizeX = fClad2RX + fMPPCDist + fMPPCHalfL + 1. * cm;
  // fWorldSizeY = fClad2RY + fMPPCDist + fMPPCHalfL + 1. * cm;
  // fWorldSizeZ = fWLSfiberZ + fMPPCDist + fMPPCHalfL + 1. * cm;

  // fCoupleRX = fWorldSizeX;
  // fCoupleRY = fWorldSizeY;
  // fCoupleZ = (fWorldSizeZ - fWLSfiberZ) / 2.;

  // fClrfiberHalfL = fMPPCHalfL;
  // fMirrorRmax = fClad2RY;

  // fCoupleOrigin = 0. + fWLSfiberZ + fCoupleZ;
  // fMirrorOrigin = 0. - fWLSfiberZ - fMirrorZ;
  // fMPPCOriginX = std::sin(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
  // fMPPCOriginZ = -fCoupleZ + std::cos(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
  fMPPCOriginZ = 0. - fWLSfiberZ - fMPPCZ;
  fCoupleOrigin = 0. - fWLSfiberZ - fClrfiberZ;
  //////////////////////////////////////////////////////////////////////////////
  // 两层光纤平面之间的间距（半长）
  fFiberSpaceHalfL = fFiberShape1Space + fShape1HalfLength + fClad1RX;
  /////////////////////////////////////////////////////////////////////////////
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetPhotonDetGeometry(G4String shape)
// Set the Geometry of the PhotonDet detector
// Pre:  shape must be either "Circle" and "Square"
{
  if (shape == "Circle" || shape == "Square")
    fMPPCShape = shape;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetNumberOfCladding(G4int num)
// Set the number of claddings
// Pre: 0 <= num <= 2
{
  fNumOfCladLayers = num;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetWLSLength(G4double length)
// Set the TOTAL length of the WLS fiber
{
  fWLSfiberZ = length;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetWLSRadius(G4double radius)
// Set the Y radius of WLS fiber
{
  fWLSfiberRY = radius;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetClad1Radius(G4double radius)
// Set the Y radius of Cladding 1
{
  fClad1RY = radius;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetClad2Radius(G4double radius)
// Set the Y radius of Cladding 2
{
  fClad2RY = radius;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetPhotonDetHalfLength(G4double halfL)
// Set the half length of the PhotonDet detector
// The half length will be the radius if PhotonDet is circular
{
  fMPPCHalfL = halfL;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetGap(G4double gap)
// Set the distance between fiber end and PhotonDet
{
  fMPPCDist = gap;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetPhotonDetAlignment(G4double theta)
// Set the Aligment of PhotonDet with respect to the z axis
// If theta is 0 deg, then the detector is perfectly aligned
// PhotonDet will be deviated by theta from z axis
// facing towards the center of the fiber
{
  fMPPCTheta = theta;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetSurfaceRoughness(G4double roughness)
// Set the Surface Roughness between Cladding 1 and WLS fiber
// Pre: 0 < roughness <= 1
{
  fSurfaceRoughness = roughness;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetMirrorPolish(G4double polish)
// Set the Polish of the mirror, polish of 1 is a perfect mirror surface
// Pre: 0 < polish <= 1
{
  fMirrorPolish = polish;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetMirrorReflectivity(G4double reflectivity)
// Set the Reflectivity of the mirror, reflectivity of 1 is a perfect mirror
// Pre: 0 < reflectivity <= 1
{
  fMirrorReflectivity = reflectivity;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetPhotonDetPolish(G4double polish)
// Set the Polish of the PhotonDet, polish of 1 is a perfect mirror surface
// Pre: 0 < polish <= 1
{
  fMPPCPolish = polish;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetPhotonDetReflectivity(G4double reflectivity)
// Set the Reflectivity of the PhotonDet, reflectivity of 1 is a perfect mirror
// Pre: 0 < reflectivity <= 1
{
  fMPPCReflectivity = reflectivity;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetMirror(G4bool flag)
// Toggle to place the mirror or not at one end (-z end) of the fiber
// True means place the mirror, false means otherwise
{
  fMirrorToggle = flag;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetXYRatio(G4double r)
// Set the ratio of the x and y radius of the ellipse (x/y)
// a ratio of 1 would produce a circle
{
  fXYRatio = r;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetBarLength(G4double length)
// Set the length of the scintillator bar
{
  fBarLength = length;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetBarBase(G4double side)
// Set the side of the scintillator bar
{
  fBarBase = side;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetHoleRadius(G4double radius)
// Set the radius of the fiber hole
{
  fHoleRadius = radius;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetCoatingThickness(G4double thick)
// Set thickness of the coating on the bars
{
  fCoatingThickness = thick;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void WLSDetectorConstruction::SetCoatingRadius(G4double radius)
// Set inner radius of the corner bar coating
{
  fCoatingRadius = radius;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetWLSFiberLength() { return fWLSfiberZ; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetBarLength() { return fBarLength; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetBarBase() { return fBarBase; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetHoleRadius() { return fHoleRadius; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetHoleLength() { return fHoleLength; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetFiberRadius() { return GetWLSFiberRMax(); }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetCoatingThickness()
{
  return fCoatingThickness;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetCoatingRadius() { return fCoatingRadius; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetWLSFiberEnd()
{
  return 0. + fWLSfiberZ;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetWLSFiberRMax()
{
  if (fNumOfCladLayers == 2)
    return fClad2RY;
  if (fNumOfCladLayers == 1)
    return fClad1RY;
  return fWLSfiberRY;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4double WLSDetectorConstruction::GetSurfaceRoughness()
{
  return fSurfaceRoughness;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

// Return True if the fiber construction is ideal
G4bool WLSDetectorConstruction::IsPerfectFiber()
{
  return fSurfaceRoughness == 1. && fXYRatio == 1. &&
         (!fMirrorToggle || (fMirrorPolish == 1. && fMirrorReflectivity == 1.));
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4Material *WLSDetectorConstruction::FindMaterial(G4String name)
{
  G4Material *material = G4Material::GetMaterial(name, true);
  return material;
}
////////////////////////////////////////////////////////////////////////////////////
void WLSDetectorConstruction::SetFiberShape1Space(G4double length)
{
  // 设置光纤与待测物体之间的距离
  fFiberShape1Space = length;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
void WLSDetectorConstruction::SetShape1HalfLength(G4double HalfL)
{
  // 设置待测物厚度(半长)
  fShape1HalfLength = HalfL;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
void WLSDetectorConstruction::SetNumOfFiberLayers(G4int num)
{
  // 设置光纤放置层数
  fNumOfFiberLayers = num;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
void WLSDetectorConstruction::SetNumOfFibers(G4int num)
{
  // 设置每层光纤数量（1根光纤只会被放置1层并位于世界中心，其他设置距离的参数不起作用）
  fNumOfFibers = num;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
void WLSDetectorConstruction::SetShape1(G4bool flag)
// 放置待测物体标志
{
  fShape1Toggle = flag;
  G4RunManager::GetRunManager()->GeometryHasBeenModified();
}
////////////////////////////////////////////////////////////////////////////////////